package chapter_5.demo6;

import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.stream.Stream;

/**
 * @author: hero生仔
 * <p>
 * 构建流
 */
public class Solution {
    public static void main(String[] args) {
        extracted01();

        extracted02();

        extracted03();

        extracted04();

        Stream.generate(Math::random)
                .limit(5)
                .forEach(System.out::println);
    }

    private static void extracted03() {
        // 由文件创建流
        /*
        使用Files.lines得到一个流，其中的每个元素都是给定文件中的一行。然后，你
        可以对line调用split方法将行拆分成单词。应该注意的是，你该如何使用flatMap产生一个扁
        平的单词流，而不是给每一行生成一个单词流。最后，把distinct和count方法链接起来，数
        数流中有多少各不相同的单词。
         */
        long count = 0;
        try (Stream<String> lines = Files.lines(Paths.get("data.txt"), Charset.defaultCharset())) {
            count = lines.flatMap(line -> Arrays.stream(line.split(" ")))
                    .distinct()
                    .count();
        } catch (IOException e) {

        }
    }

    private static void extracted04() {
        // 由函数生成流：创建无限流；Stream API 提供两个静态方法从函数生成流：Stream.iterate 和 Stream.generate。
        /*
        这两个操作可以创建所谓的无限流：不像从固定集合创建的流那样有固定大小的流。由iterate
        和generate产生的流会用给定的函数按需创建值，因此可以无穷无尽地计算下去！一般来说，
        应该使用limit(n)来对这种流加以限制，以避免打印无穷多个值。

        一般来说，在需要依次生成一系列值的时候应该使用iterate，比如一系列日期：1月31日，2月1日，依此类推。
         */
        Stream.iterate(0, n -> n + 2)
                .limit(10)
                .forEach(System.out::println);


        /*
         打印斐波那契数列
         0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55…数列中开始的两个数字是0和1，后续的每个数字都是前两个数字之和。
        斐波纳契元组序列与此类似，是数列中数字和其后续数字组成的元组构成的序列：(0, 1), (1, 1), (1, 2), (2, 3), (3, 5), (5, 8), (8, 13), (13, 21) …

        你的任务是用iterate方法生成斐波纳契元组序列中的前20个元素
         */
        Stream.iterate(new int[]{0, 1}, t -> new int[]{t[1], t[0] + t[1]})
                .limit(20)
                .forEach(t -> System.out.println("(" + t[0] + "," + t[1] +")"));


        Stream.iterate(new int[]{0, 1}, t -> new int[]{t[1], t[0] + t[1]})
                .limit(20)
                // 如果你只想打印正常的斐波纳契数列，可以使用map提取每个元组中的第一个元素
                .map(t -> t[0])
                .forEach(System.out::println);
    }

    private static void extracted02() {
        // 由数组创建流
        int sum = Arrays.stream(new int[]{1, 2, 3, 4}).sum();
        System.out.println(sum);
    }

    private static void extracted01() {
        // 由值创建流
        Stream<String> stream = Stream.of("Java8", "Lambda", "In", "Action");
        stream.map(String::toUpperCase).forEach(System.out::println);

        // 也可以得到一个空流
        Stream<String> emptyStream = Stream.empty();
    }
}
